home *** CD-ROM | disk | FTP | other *** search
/ ftp.mactech.com 2010 / ftp.mactech.com.tar / ftp.mactech.com / challenge / 12.04-Apr96 / LifeTestCode DR3.sit / Life TestCode DR3 / LifeFile.c < prev    next >
Text File  |  1996-03-31  |  9KB  |  334 lines

  1. /* LifeFile.c    */
  2. /* ©Ludovic Nicolle 1996    */
  3.  
  4.  
  5. #include "LifeFile.h"
  6.  
  7. /*
  8. CreateLifeFile first is a standard save dialog to create 
  9. a file of type 'LIFE' and creator 'MULI' .
  10. The file size is set to 4 and the four bytes are set to 0 to 
  11. reflect the fact there is originally no LifeRun in the file.
  12. If a file is open, its reference number is placed in refnum
  13. */
  14. OSErr CreateLifeFile(short    *refNum, FSSpec *fileSpec)
  15. {
  16.     OSErr        iErr = noErr;
  17.     Str255        savePrompt = "\pSave LifeFile™ as…";
  18.     Str255        saveDefault = "\pUntitled";
  19.     StandardFileReply    reply;
  20.     long        ioCount = 4;
  21.     long        numRuns = 0;
  22.     
  23.     StandardPutFile(savePrompt, saveDefault, &reply);
  24.     if (!reply.sfGood)
  25.         return userCanceledErr;
  26.     if (reply.sfReplacing)
  27.         iErr = FSpDelete(&reply.sfFile);
  28.     if (iErr)
  29.         return iErr;
  30.     
  31.     iErr = FSpCreate(&reply.sfFile, MutantLifeCreator, LifeFileType, smSystemScript);
  32.     if (iErr == noErr)
  33.     {
  34.         iErr = FSpOpenDF(&reply.sfFile, fsCurPerm, refNum);
  35.         if (iErr)
  36.         {
  37.             FSpDelete(&reply.sfFile);/*cannot open file, so delete it*/
  38.             return iErr;
  39.         }
  40.     }
  41.     if (refNum != 0)    /*paranoïa check!*/
  42.     {    
  43.         iErr = SetFPos(*refNum, fsFromStart, 0);
  44.         iErr = FSWrite(*refNum, &ioCount, &numRuns);
  45.     }
  46.     *fileSpec = reply.sfFile;
  47.     return iErr;
  48. }
  49. //#define LifeFileType 'LIFE'
  50. //#define MutantLifeCreator    'MULI'
  51.  
  52. /*
  53. OpenLifeFile displays the StandardGetFile to open a LifeFile
  54. then open it. if 
  55. */
  56. OSErr OpenLifeFile(short *refNum, FSSpec *fileSpec)
  57. {
  58.     OSErr        iErr = noErr;
  59.     SFTypeList    typeList = {'LIFE'};
  60.     StandardFileReply    reply;
  61.     StandardGetFile(nil, 1, typeList, &reply);
  62.     if (!reply.sfGood)
  63.         return userCanceledErr;
  64.     iErr = FSpOpenDF(&reply.sfFile, fsCurPerm, refNum);
  65.     *fileSpec = reply.sfFile;
  66.     return iErr;
  67. }
  68.  
  69. OSErr CloseLifeFile(short *refNum)
  70. {
  71.     OSErr    iErr;
  72.     
  73.     if (*refNum == 0)
  74.         return fnOpnErr;
  75.     iErr = FSClose(*refNum);
  76.     *refNum = 0;
  77.     return iErr;
  78. }
  79.  
  80. OSErr AppendLifeRun(short refNum, LifeRunPtr theRun)
  81. {
  82.     OSErr    iErr;
  83.     long    ioCount;
  84.     unsigned long    numRuns;
  85.     long    index;
  86.     long    logEOF;
  87.     LifeRun    localRun;
  88.     long    filePos;
  89.     
  90.     if (refNum == 0)
  91.         return rfNumErr;    /*    0 is invalid file number*/
  92.     iErr = GetEOF(refNum, &logEOF);
  93.     iErr = SetFPos(refNum, fsFromStart, 0);
  94.     ioCount = sizeof(long);
  95.     iErr = FSRead(refNum, &ioCount, &numRuns);
  96.     if (iErr)
  97.         return iErr;
  98.     if (numRuns > kMaxRuns)
  99.         return tooManyRunsErr;
  100. /* crawl to find logically the end of last run. This should
  101. give the same value as logEOF    */
  102.      for (index = 0; index < numRuns; index++)
  103.     {
  104.         ioCount = sizeof(LifeRun);
  105.         iErr = FSRead(refNum, &ioCount, &localRun);
  106.         if (iErr)
  107.             return iErr;
  108.  
  109.         iErr = GetFPos(refNum, &filePos);
  110.         filePos +=    localRun.steps *
  111.                     (sizeof(long) +    /* stepvalue*/
  112.                     localRun.rbytes * 
  113.                     (localRun.worldSize.bottom - localRun.worldSize.top));
  114.         if (filePos > logEOF)
  115.             return lifeFileCorruptErr; 
  116.         iErr = SetFPos(refNum, fsFromStart, filePos);
  117.     }
  118.     
  119.     if (iErr == noErr)
  120.     {
  121.         localRun = *theRun;
  122.         localRun.steps = 0;    /* initially set to 0 */
  123.         ioCount = sizeof(LifeRun);
  124.         iErr = FSWrite(refNum, &ioCount, &localRun);
  125.         if (iErr == noErr)
  126.         {
  127.             iErr = SetFPos(refNum, fsFromStart, 0);
  128.             numRuns++;
  129.             ioCount = sizeof(long);
  130.             iErr = FSWrite(refNum, &ioCount, &numRuns);
  131.         }
  132.     }
  133.     return iErr;
  134. }
  135.  
  136. OSErr SetComputedGen(short refNum, long whichRun, long computedGen)
  137. {
  138.     OSErr    iErr;
  139.     long    ioCount;
  140. //    unsigned long    numRuns;
  141.     LifeRun    localRun;
  142.     long    runlength;
  143.     long    filePos;
  144.     
  145.     iErr = ReadLifeRun(refNum, &localRun, whichRun);
  146.     if (iErr)
  147.         return iErr;
  148. /*    we skipped the entire run with the call to ReadLifeRun
  149.     so we rewind the necessary length*/
  150.     runlength =    localRun.steps *
  151.                 (sizeof(long) +
  152.                 localRun.rbytes * 
  153.                 (localRun.worldSize.bottom - localRun.worldSize.top));
  154.     iErr = GetFPos(refNum, &filePos);
  155.     filePos -= runlength;
  156.     filePos -= 20;/*this is the offset from computedGen to the
  157.                     end of the LifeRun    */
  158.     iErr = SetFPos(refNum, fsFromStart, filePos);
  159.     ioCount = sizeof(long);
  160.     iErr = FSWrite(refNum, &ioCount, &computedGen);
  161.     return iErr;
  162. }
  163.  
  164.  
  165. OSErr AppendLifeWorld(short refNum, BitMapStep *lifeWorld)
  166. {
  167.     OSErr    iErr;
  168.     long    ioCount;
  169.     unsigned long    numRuns;
  170.     long    index;
  171.     long    logEOF;
  172.     LifeRun    localRun;
  173.     long    filePos;
  174.     long    runlength;
  175.     
  176.     if (refNum == 0)
  177.         return rfNumErr;    /*    0 is invalid file number*/
  178.     iErr = GetEOF(refNum, &logEOF);
  179.     iErr = SetFPos(refNum, fsFromStart, 0);
  180.     ioCount = sizeof(long);
  181.     iErr = FSRead(refNum, &ioCount, &numRuns);
  182.     if (numRuns > kMaxRuns)
  183.         return tooManyRunsErr;
  184.     if (numRuns == 0)
  185.         return noRunsErr;
  186. /* crawl to find logically the end of last run. This should
  187. give the same value as logEOF    */
  188.     
  189.      for (index = 0; index < numRuns; index++)
  190.     {
  191.         ioCount = sizeof(LifeRun);
  192.         iErr = FSRead(refNum, &ioCount, &localRun);
  193.         if (iErr)
  194.             return iErr;
  195.  
  196.         iErr = GetFPos(refNum, &filePos);
  197.         runlength =    localRun.steps *
  198.                     (sizeof(long) +
  199.                     localRun.rbytes * 
  200.                     (localRun.worldSize.bottom - localRun.worldSize.top));
  201.         filePos += runlength;
  202.         if (filePos > logEOF)
  203.             return lifeFileCorruptErr; 
  204.         iErr = SetFPos(refNum, fsFromStart, filePos);
  205.     }
  206.     if (iErr)
  207.         return iErr;
  208.         /* Simple siz checking    */
  209.     if ((localRun.worldSize.top != lifeWorld->cellsBM.bounds.top) ||
  210.         (localRun.worldSize.left != lifeWorld->cellsBM.bounds.left) ||
  211.         (localRun.worldSize.bottom != lifeWorld->cellsBM.bounds.bottom) ||
  212.         (localRun.worldSize.right != lifeWorld->cellsBM.bounds.right) ||
  213.         (localRun.rbytes != lifeWorld->cellsBM.rowBytes))
  214.         return badBitMapSizeErr;
  215. /* write the stepvalue    */
  216.     ioCount = sizeof(long);
  217.     iErr = FSWrite(refNum, &ioCount, &lifeWorld->stepvalue);
  218.     if (iErr)
  219.         return iErr;
  220.     ioCount = lifeWorld->cellsBM.rowBytes * 
  221.         (lifeWorld->cellsBM.bounds.bottom - lifeWorld->cellsBM.bounds.top);
  222.     iErr = FSWrite(refNum, &ioCount, lifeWorld->cellsBM.baseAddr);
  223. /* now update the LifeRun structure    */
  224.     ioCount = sizeof(long);
  225.     localRun.steps++;
  226.     iErr = SetFPos(refNum, fsFromStart, filePos - runlength - 4);
  227.     iErr = FSWrite(refNum, &ioCount, &localRun.steps);
  228.     return iErr;
  229. }
  230.  
  231. OSErr GetRunNumber(short refNum, long *outRuns)
  232. {
  233.     OSErr    iErr;
  234.     long    ioCount;
  235.     
  236.     if (refNum == 0)
  237.         return rfNumErr;    /*    0 is invalid file number*/
  238.     iErr = SetFPos(refNum, fsFromStart, 0);
  239.     ioCount = sizeof(long);
  240.     iErr = FSRead(refNum, &ioCount, outRuns);
  241.     return iErr;
  242. }
  243.  
  244. OSErr ReadLifeRun(short refNum, LifeRun *theRun, long whichRun)
  245. {
  246.     OSErr    iErr;
  247.     long    ioCount;
  248.     unsigned long    numRuns;
  249.     long    index;
  250.     long    logEOF;
  251.     long    filePos;
  252.     long    runlength;
  253.     
  254.     if (refNum == 0)
  255.         return rfNumErr;    /*    0 is invalid file number*/
  256.     iErr = GetEOF(refNum, &logEOF);
  257.     iErr = SetFPos(refNum, fsFromStart, 0);
  258.     ioCount = sizeof(long);
  259.     iErr = FSRead(refNum, &ioCount, &numRuns);
  260.     if (numRuns < whichRun)
  261.         return runAbsentErr;
  262.     if (whichRun == 0)
  263.         return runAbsentErr;
  264.     
  265. /* crawl to find logically the asked run*/
  266.      for (index = 0; index < whichRun; index++)
  267.     {
  268.         ioCount = sizeof(LifeRun);
  269.         iErr = FSRead(refNum, &ioCount, theRun);
  270.         if (iErr)
  271.             return iErr;
  272.  
  273.         iErr = GetFPos(refNum, &filePos);
  274.         runlength =    theRun->steps *
  275.                     (sizeof(long) +
  276.                     theRun->rbytes *
  277.                     (theRun->worldSize.bottom - theRun->worldSize.top));
  278.  
  279.         filePos += runlength;
  280.         if (filePos > logEOF)
  281.             return lifeFileCorruptErr; 
  282.         iErr = SetFPos(refNum, fsFromStart, filePos);
  283.     }
  284.     return iErr;
  285. }
  286.  
  287. OSErr ReadLifeWorld(short refNum, BitMapStep *lifeWorld, 
  288.                             long whichRun, long step)
  289. {
  290.     OSErr    iErr;
  291.     long    ioCount;
  292.     long    filePos;
  293.     long    runlength;
  294.     LifeRun    localRun;
  295.  
  296.     iErr = ReadLifeRun(refNum, &localRun, whichRun);
  297.     if (iErr)
  298.         return iErr;
  299.     if ((step > localRun.steps) || (step < 1))
  300.         return stepAbsentErr;
  301. /*    we skipped the entire run with the call to ReadLifeRun
  302.     so we rewind the necessary length*/
  303.     runlength =    (localRun.steps - step + 1) *
  304.                 (sizeof(long) +
  305.                 localRun.rbytes * 
  306.                 (localRun.worldSize.bottom - localRun.worldSize.top));
  307.     iErr = GetFPos(refNum, &filePos);
  308.     filePos -= runlength;
  309.     iErr = SetFPos(refNum, fsFromStart, filePos);
  310.     
  311. /* Now read the stepvalue    */
  312.     ioCount = sizeof(long);
  313.     iErr = FSRead(refNum, &ioCount, &lifeWorld->stepvalue);
  314.     lifeWorld->cellsBM.rowBytes = localRun.rbytes;
  315.     lifeWorld->cellsBM.bounds = localRun.worldSize;
  316.  
  317.     if ((localRun.worldSize.top != lifeWorld->cellsBM.bounds.top) ||
  318.             (localRun.worldSize.left != lifeWorld->cellsBM.bounds.left) ||
  319.             (localRun.worldSize.bottom != lifeWorld->cellsBM.bounds.bottom) ||
  320.             (localRun.worldSize.right != lifeWorld->cellsBM.bounds.right) ||
  321.             (localRun.rbytes != lifeWorld->cellsBM.rowBytes))
  322.         return badBitMapSizeErr;
  323.  
  324. /* And finally read the bitmap data    */
  325.     ioCount = lifeWorld->cellsBM.rowBytes * 
  326.         (lifeWorld->cellsBM.bounds.bottom - lifeWorld->cellsBM.bounds.top);
  327.     lifeWorld->cellsBM.baseAddr = NewPtr(ioCount);
  328.     if (lifeWorld->cellsBM.baseAddr == nil)
  329.         return memFullErr;
  330.     iErr = FSRead(refNum, &ioCount, lifeWorld->cellsBM.baseAddr);
  331.     return iErr;
  332. }
  333.  
  334.